#include "DevLog.h"
#include "time.h"

/**
 * @brief 当前写入记录;
 */
uint32_t g_ShakeCnt;

/**
 * @brief 当前写入记录
 */
uint32_t g_OpenCnt;

/**
 * @brief 
 * 
 */
void DevLog_Init(void)
{
	EfErrCode Err = easyflash_init();
	if(Err != EF_NO_ERR)
	{
		printf("dev log init err is %s\n", ef_err_to_str(Err));
	}
	else 
	{
//		printf("dev log init is ok..\n");
	}
	
	
	/**
	 * @brief 加载震动/开窗次数
	 */
	g_ShakeCnt = 0;
	g_OpenCnt = 0;
	DevLog_ShakeCount_Get(&g_ShakeCnt);
	DevLog_OpenCount_Get(&g_OpenCnt);
//	printf("g_ShakeCnt: %d\n", g_ShakeCnt);
//	printf("g_OpenCnt:  %d\n", g_OpenCnt);
}

/**
 * @brief 写入块数据
 * 
 * @param key key name
 * @param buf_wr 待写入的数据块 [ !NULL: 新增/覆盖; NULL:删除; ]
 * @param len_wr 待写入的数据块长度
 * @return EfErrCode 
 * @retval 
 *  成功: EF_NO_ERR
 *  其他: 失败
 */
EfErrCode dev_log_write_block(const char *key, const void * buf_wr, uint32_t len_wr)
{
	return ef_set_env_blob(key, buf_wr, len_wr);
}

/**
 * @brief 读取数据
 * 
 * @param key key name
 * @param buf_rd 待读取的数据缓冲区
 * @param len_rd 待读取的数据长度
 * @return EfErrCode 
 * @retval 
 *  成功: EF_NO_ERR
 *  其他: 失败
 */
#define STATIC_BUF_SIZE		(128)
 
EfErrCode dev_log_read_block(const char *key, void* buf_rd, uint32_t len_rd)
{
	static char value[STATIC_BUF_SIZE + 1];
    size_t get_size;

    if ((get_size = ef_get_env_blob(key, value, STATIC_BUF_SIZE, NULL)) > 0) 
	{
		if(len_rd > get_size)  { len_rd = get_size; }
		memcpy(buf_rd, value, len_rd);
		return EF_NO_ERR;
    }
	return EF_ENV_NAME_ERR;
}

/**
 * @brief 键值是否添加
 * 
 * @param key key name 
 * @return true 已添加
 * @return false 未添加
 */
bool is_key_add(const char *key)
{
	env_node_obj_t env={0};
	return ef_get_env_obj(key, env);
}

/**
 * @brief 写入震动次数;
 * 
 * @param ShakeCount 待写入的震动次数
 * @return EfErrCode 
 */
EfErrCode DevLog_ShakeCount_Set(uint32_t ShakeCount)
{
	return dev_log_write_block("ShakeCnt", &ShakeCount, sizeof(ShakeCount));
}

/**
 * @brief 获取震动次数
 * 
 * @param ShakeCount : 震动次数缓冲区
 * @return EfErrCode 
 */
EfErrCode DevLog_ShakeCount_Get(uint32_t* ShakeCount)
{
	return dev_log_read_block("ShakeCnt", ShakeCount, sizeof(uint32_t));
}

/**
 * @brief 清空日志次数
 * 
 * @return EfErrCode 
 */
EfErrCode DevLog_ShakeCount_Clean(void)
{
	EfErrCode Err;
	uint32_t Tmp=0;
	Err = dev_log_write_block("ShakeCnt", &Tmp, sizeof(Tmp));
	if(Err == EF_NO_ERR) { g_ShakeCnt=0; }
	return Err;
}

/**
 * @brief 写入开窗次数;
 * 
 * @param OpenCount 待写入的开窗次数
 * @return EfErrCode 
 */
EfErrCode DevLog_OpenCount_Set(uint32_t OpenCount)
{
	return dev_log_write_block("OpenCnt", &OpenCount, sizeof(OpenCount));
}

/**
 * @brief 获取开窗次数
 * 
 * @param OpenCount : 开窗次数缓冲区
 * @return EfErrCode 
 */
EfErrCode DevLog_OpenCount_Get(uint32_t* OpenCount)
{
	return dev_log_read_block("OpenCnt", OpenCount, sizeof(uint32_t));
}

/**
 * @brief 清空日志次数
 * 
 * @return EfErrCode 
 */
EfErrCode DevLog_OpenCount_Clean(void)
{
	EfErrCode Err;
	uint32_t Tmp=0;
	Err = dev_log_write_block("OpenCnt", &Tmp, sizeof(Tmp));
	if(Err == EF_NO_ERR) { g_OpenCnt=0; }
	return Err;
}


/**
 * @brief 新增震动记录
 * 
 * @param ShakeLog 待添加的震动日志
 * @return EfErrCode 
 */
EfErrCode DevLog_Shake_Add(Log_Shake_t ShakeLog)
{
	EfErrCode Err;
	char KeyBuf[32]={0};

	if(g_ShakeCnt >= LOG_SHAKE_MAX_COUNT)
	{
		g_ShakeCnt = 0;
	}

	sprintf(KeyBuf, "Shake_%d", g_ShakeCnt);		// 0, 1, 2, 3 .... LOG_SHAKE_MAX_COUNT-1
	// printf("shake add buf: %s\n", KeyBuf);

	Err = dev_log_write_block(KeyBuf, &ShakeLog, sizeof(ShakeLog));
	if(Err == EF_NO_ERR)
	{
		g_ShakeCnt++;
		DevLog_ShakeCount_Set(g_ShakeCnt);
	}

	return Err;
}


/**
 * @brief 获取震动记录
 * 
 * @param LogCnt 记录次数 : 1, 2, 3, .... LOG_SHAKE_MAX_COUNT
 * @param ShakeLog 记录缓冲区
 * @return EfErrCode 
 */
EfErrCode DevLog_Shake_Get(uint32_t LogCnt , Log_Shake_t* ShakeLog)
{
	char KeyBuf[32]={0};

	if( LogCnt >= LOG_SHAKE_MAX_COUNT)  {  return EF_READ_ERR; }

	sprintf(KeyBuf, "Shake_%d", LogCnt);

	return dev_log_read_block(KeyBuf, ShakeLog, sizeof(Log_Shake_t));
}

/**
 * @brief 清除所有震动记录
 * 
 * @return EfErrCode 
 */
EfErrCode DevLog_Shake_Clear(void)
{
	uint32_t i=0;
	char KeyBuf[32]={0};

	DevLog_ShakeCount_Clean();
	
	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		memset(KeyBuf, 0, sizeof(KeyBuf));
		sprintf(KeyBuf, "Shake_%d", i);		// 0, 1, 2, 3 ... LOG_SHAKE_MAX_COUNT-1

		ef_del_env(KeyBuf);
	}
	return EF_NO_ERR;
}

/**
 * @brief 打印震动信息
 * 
 * @param ShakeLog 
 */
void DevLog_Shake_Print(int Count, Log_Shake_t ShakeLog)
{
	printf("/* [%d] Shake log: short addr [%04X], time [%s]\n", Count, ShakeLog.ShortAddr ,time_to_str(ShakeLog.timeStamp));
}

/**
 * @brief 打印所有的震动信息
 * 
 */
void DevLog_Shake_All_Print(void)
{
	uint32_t i=0;
	Log_Shake_t ShakeLog={0};

	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		if(DevLog_Shake_Get(i, &ShakeLog) == EF_NO_ERR)
		{
			DevLog_Shake_Print(i+1, ShakeLog);
		}
	}
}

/**
 * @brief 测试
 * 
 * @return void 
 */
void DevLog_Shake_Test(void)
{
	uint32_t i=0;
	Log_Shake_t Shake;
	EfErrCode Err;
	printf("DevLog_Shake_Test\n");
	// add
	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		Shake.timeStamp = i;
		Err = DevLog_Shake_Add(Shake);
		printf("Shake [%d] add result is [%s]\n", i, ef_err_to_str(Err));
	}
	// get
	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		Shake.timeStamp = 0;
		Err = DevLog_Shake_Get(i, &Shake);
		printf("Shake [%d] get result is [%s] , timeStamp: %d\n", i, ef_err_to_str(Err), Shake.timeStamp);
	}
	
	// clear
	printf("Clear all shake log\n");
	DevLog_Shake_Clear();

	// get
	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		Shake.timeStamp = 0;
		Err = DevLog_Shake_Get(i, &Shake);
		printf("Shake [%d] get result is [%s] , timeStamp: %d\n", i, ef_err_to_str(Err), Shake.timeStamp);
	}
	
	// add
	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		Shake.timeStamp = i;
		Err = DevLog_Shake_Add(Shake);
		printf("Shake [%d] add result is [%s]\n", i, ef_err_to_str(Err));
	}
	
	// get
	for(i=0; i<LOG_SHAKE_MAX_COUNT; i++)
	{
		Shake.timeStamp = 0;
		Err = DevLog_Shake_Get(i, &Shake);
		printf("Shake [%d] get result is [%s] , timeStamp: %d\n", i, ef_err_to_str(Err), Shake.timeStamp);
	}
}


/**
 * @brief 新增震动记录
 * 
 * @param OpenLog 待添加的开窗日志
 * @return EfErrCode 
 */
EfErrCode DevLog_Open_Add(Log_Open_t OpenLog)
{
	EfErrCode Err;
	char KeyBuf[32]={0};

	if(g_OpenCnt >= LOG_OPEN_MAX_COUNT)		// 循环添加;
	{
		g_OpenCnt = 0;
	}

	sprintf(KeyBuf, "Open_%d", g_OpenCnt);		// 0, 1, 2, 3 ... LOG_OPEN_MAX_COUNT-1

	Err = dev_log_write_block(KeyBuf, &OpenLog, sizeof(OpenLog));
	if(Err == EF_NO_ERR)
	{
		g_OpenCnt++;
		DevLog_OpenCount_Set(g_OpenCnt);
	}
	
	return Err;
}

/**
 * @brief 获取开窗记录
 * 
 * @param LogCnt 记录次数 : 1, 2, 3, .... LOG_OPEN_MAX_COUNT
 * @param OpenLog 记录缓冲区
 * @return EfErrCode 
 */
EfErrCode DevLog_Open_Get(uint32_t LogCnt , Log_Open_t* OpenLog)
{
	char KeyBuf[32]={0};

	if( LogCnt >= LOG_OPEN_MAX_COUNT)  {  return EF_READ_ERR; }

	sprintf(KeyBuf, "Open_%d", LogCnt);

	return dev_log_read_block(KeyBuf, OpenLog, sizeof(Log_Open_t));
}

/**
 * @brief 清除所有震动记录
 * 
 * @return EfErrCode 
 */
EfErrCode DevLog_Open_Clear(void)
{
	uint32_t i=0;
	char KeyBuf[32]={0};

	DevLog_OpenCount_Clean();
	
	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		memset(KeyBuf, 0, sizeof(KeyBuf));
		sprintf(KeyBuf, "Open_%d", i);		// 0, 1, 2, 3 ... LOG_OPEN_MAX_COUNT-1
		
		ef_del_env(KeyBuf);
	}
	return EF_NO_ERR;
}

/**
 * @brief 打印开窗信息
 * 
 * @param OpenLog 
 */
void DevLog_Open_Print(int Count, Log_Open_t OpenLog)
{
	printf("/* [%d] Open log: short addr [%04X], time [%s]\n", Count, OpenLog.ShortAddr ,time_to_str(OpenLog.timeStamp));
}

/**
 * @brief 打印所有的开窗信息
 * 
 */
void DevLog_Open_All_Print(void)
{
	uint32_t i=0;
	Log_Open_t OpenLog={0};

	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		if(DevLog_Open_Get(i, &OpenLog) == EF_NO_ERR)
		{
			DevLog_Open_Print(i+1, OpenLog);
		}
	}
}


/**
 * @brief 测试
 * 
 * @return void 
 */
void DevLog_Open_Test(void)
{
	uint32_t i=0;
	Log_Open_t Open;
	EfErrCode Err;
	
	printf("DevLog_Open_Test......\n");
	
	// add
	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		Open.timeStamp = i;
		Err = DevLog_Open_Add(Open);
		printf("Open [%d] add result is [%s]\n", i, ef_err_to_str(Err));
	}
	// get
	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		Open.timeStamp = 0;
		Err = DevLog_Open_Get(i, &Open);
		printf("Open [%d] add result is [%s], timeStamp: %d\n", i, ef_err_to_str(Err), Open.timeStamp);
	}
	
	// clear
	printf("Clear all Open log\n");
	DevLog_Open_Clear();

	// get
	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		Open.timeStamp = 0;
		Err = DevLog_Open_Get(i, &Open);
		printf("Open [%d] add result is [%s], timeStamp: %d\n", i, ef_err_to_str(Err), Open.timeStamp);
	}
	
	// add
	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		Open.timeStamp = i;
		Err = DevLog_Open_Add(Open);
		printf("Open [%d] add result is [%s]\n", i, ef_err_to_str(Err));
	}
	
	// get
	for(i=0; i<LOG_OPEN_MAX_COUNT; i++)
	{
		Open.timeStamp = 0;
		Err = DevLog_Open_Get(i, &Open);
		printf("Open [%d] add result is [%s], timeStamp: %d\n", i, ef_err_to_str(Err), Open.timeStamp);
	}
}

